#include "network_info.h"
#include <sys/sysinfo.h>
#include <net/if.h>
#include <sys/ioctl.h> 
#include <unistd.h> 

#define PORT 12345
#define BUFFER_SIZE 1024

// 线程函数，用于监听TCP连接并解析指令
void *tcp_listener_thread(void *arg) {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    fd_set readfds;
    struct timeval timeout;
    int *uart_fd = (int*)(arg);

    // 创建socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Listening on port %d...\n", PORT);

    while (1) {
        // 设置select的参数
        FD_ZERO(&readfds);
        FD_SET(server_fd, &readfds);

        // 设置超时时间
        timeout.tv_sec = 2; // 5秒超时
        timeout.tv_usec = 0;

        // 等待连接
        int activity = select(server_fd + 1, &readfds, NULL, NULL, &timeout);

        if (activity < 0) {
            perror("select error");
            exit(EXIT_FAILURE);
        }

        if (activity == 0) {
            // 超时，没有数据
            // printf("No data within the timeout period.\n");
            continue;
        }

        if (FD_ISSET(server_fd, &readfds)) {
            if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
                perror("accept");
                exit(EXIT_FAILURE);
            }

            // 读取数据
            while (1) {
                int read_size = read(new_socket, buffer, BUFFER_SIZE);
                if (read_size <= 0) {
                    break; // 连接关闭或读取结束
                }
                buffer[read_size] = '\0'; // 确保字符串正确终止
                printf("Received: %s\n", buffer);

                // 这里可以添加解析指令的代码
                int fd = *uart_fd;
                char buf[8] = {0xaa, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 

                if(buffer[0] == 0x88)
                {
                    if(buffer[1] <= IRON_RED_PSEUDO_COLOR && buffer[1] >= 0)
                    {
                        buf[2] = buffer[1];
                        buf[7] =  buf[1] + buf[2] + buf[3] + buf[4]  + buf[5] + buf[6];
                        serial_write(fd, buf, sizeof(buf));
                    }
                    else
                    {
                        fprintf(stderr,"Unsupport cmd!\n");
                    }
                }
                // 清空缓冲区
                memset(buffer, 0, sizeof(buffer));
            }

            close(new_socket);
        }
    }

    close(server_fd);
    return NULL;
}


static int check_file(const char* path, int type)
{
    if(!path)
    {
        fprintf(stderr,"path is null!\n");
        return -1;
    }
    struct stat info;

    if(type == TYPE_DIR)
    {
        int status = stat(path, &info);
        if (status != 0) 
        {
            if (errno == ENOENT) 
            {
                if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == 0) 
                {
                    fprintf(stderr,"Dir '%s' created\n", path);
                } 
                else 
                {
                    perror("Created Dir failed.");
                    return -1;
                }
            } 
            else 
            {
                perror("Check Dir Failed.");
                return -1;
            }
        }
    }
    else if(type == TYPE_FILE)
    {
        int  status = stat(path, &info);
        if (status != 0) 
        {
            if (errno == ENOENT) 
            {
                FILE* fp = fopen(path, "w+");
                if (fp) 
                {
                    fprintf(stderr,"File '%s' creates success.\n", path);
                    fclose(fp);
                } else 
                {
                    perror("Create File failed.");
                    return -1;
                }
            } 
            else 
            {
                perror("Check file failed.");
                return -1;
            }
        }
    }
    else
    {
        fprintf(stderr,"Type dismatch.\n");
        return -1;
    }
    return 0;
}

int create_empty_ini_file()
{
    int ret = check_file(CONFIG_DIR_NAME, TYPE_DIR);
    if(0 > ret){
        fprintf(stderr,"check_dir file!\n");
        return -1;
    }
    ret = check_file(CONFIG_INI_NAME, TYPE_FILE);
    if(0 > ret){
        fprintf(stderr,"check_config_ini file!\n");
        return -1;
    }

    return 0;
}

int write_netinfo_to_ini(void *st)
{
    char *filename = CONFIG_INI_NAME;

    NetworkConfigNetworkTcpIp *net_info = (NetworkConfigNetworkTcpIp *)st;
    void *dictionary;
    FILE *ini_file;
    int ret = -1;

    dictionary = iniparser_load(filename);
    if (!dictionary) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return ret;
    }

      /* set section */
    ret = iniparser_set(dictionary, "network", NULL);
    if (ret < 0) {
        fprintf(stderr, "cannot set section in: %s\n", filename);
        ret = -1;
        goto free_dict;
    }

    /* set key/value pair */
    ret = iniparser_set(dictionary, "network:ipv4_addr", net_info->ipv4_addr);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ret = iniparser_set(dictionary, "network:ipv4_gateway", net_info->ipv4_gateway);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ret = iniparser_set(dictionary, "network:ipv4_mask", net_info->ipv4_mask);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ret = iniparser_set(dictionary, "network:dns", net_info->dns);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ini_file = fopen(filename, "w+");
    if (!ini_file) {
        fprintf(stderr, "iniparser: cannot create example.ini\n");
        goto free_dict;
    }

    iniparser_dump_ini(dictionary, ini_file);
    fclose(ini_file);

free_dict:
    iniparser_freedict(dictionary);
    return ret;
}

int write_chipctrl_to_ini(void *st)
{
    char *filename = CONFIG_INI_NAME;
    if ( !st) {
        fprintf(stderr, "Invalid argurment\n");
        return -1;
    }

    NetworkCameraChipInfo *chip_ctrl = (NetworkCameraChipInfo *)st;
    void *dictionary;
    FILE *ini_file;

    dictionary = iniparser_load(filename);
    if (!dictionary) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return -1;
    }

      /* set section */
    int ret = iniparser_set(dictionary, "camera_chip_info", NULL);
    if (ret < 0) {
        fprintf(stderr, "cannot set section in: %s\n", filename);
        ret = -1;
        goto free_dict;
    }

    /* set key/value pair */
    char value_str[20];
    snprintf(value_str, sizeof(value_str), "%d", chip_ctrl->pseudo_color);
    ret = iniparser_set(dictionary, "camera_chip_info:pseudo_color", value_str);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    snprintf(value_str, sizeof(value_str), "%f", chip_ctrl->electronic_zoom);
    ret = iniparser_set(dictionary, "camera_chip_info:electronic_zoom", value_str);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    snprintf(value_str, sizeof(value_str), "%d", chip_ctrl->shutter_calibration);
    ret = iniparser_set(dictionary, "camera_chip_info:shutter_calibration", value_str);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    snprintf(value_str, sizeof(value_str), "%d", chip_ctrl->outdoor_mode);
    ret = iniparser_set(dictionary, "camera_chip_info:outdoor_mode", value_str);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ini_file = fopen(filename, "w+");
    if (!ini_file) {
        fprintf(stderr, "iniparser: cannot create example.ini\n");
        goto free_dict;
    }

    iniparser_dump_ini(dictionary, ini_file);
    fclose(ini_file);

free_dict:
    iniparser_freedict(dictionary);
    return ret;
}

int get_netinfo_from_ini(NetworkConfigNetworkTcpIp *net_info)
{
   char *filename = CONFIG_INI_NAME;

    dictionary  *   ini ;
    int             rInt;
    const char*  rSrc;

    fprintf(stderr, "[%04d]:filename->%s\n",__LINE__, filename);
    ini = iniparser_load(filename);
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return -1 ;
    }

    // memset(net_info, 0x0, sizeof(NetInfo));
    rSrc = iniparser_getstring(ini, "network:ipv4_addr", NULL);
    if(rSrc){
        strncpy(net_info->ipv4_addr, rSrc, IP_ADDR_MAX_LENGTH - 1);
        net_info->ipv4_addr[IP_ADDR_MAX_LENGTH - 1] = '\0';
    }
    
    rSrc = iniparser_getstring(ini, "network:ipv4_gateway", NULL);
    if(rSrc){
        strncpy(net_info->ipv4_gateway, rSrc, IP_ADDR_MAX_LENGTH - 1);
        net_info->ipv4_gateway[IP_ADDR_MAX_LENGTH - 1] = '\0';
    }
   
    rSrc = iniparser_getstring(ini, "network:ipv4_mask", NULL);
    if(rSrc){
        strncpy(net_info->ipv4_mask, rSrc, IP_ADDR_MAX_LENGTH - 1);
        net_info->ipv4_mask[IP_ADDR_MAX_LENGTH -1] = '\0';
    }
    
    rSrc = iniparser_getstring(ini, "network:dns", NULL);
    if(rSrc){
        strncpy(net_info->dns, rSrc, IP_ADDR_MAX_LENGTH - 1);
        net_info->dns[IP_ADDR_MAX_LENGTH-1] = '\0';
    }   
    
    char mac_addr[18] = {0};
    int ret = get_physical_addr("eth0", mac_addr);
    if(ret == 0)
    {
        memcpy(net_info->mac , mac_addr, sizeof(mac_addr));
    }

    iniparser_freedict(ini);
    return 0 ;
}

int get_chipctrl_from_ini(NetworkCameraChipInfo *chip_ctrl)
{
    char *filename =  CONFIG_INI_NAME;
    
    dictionary  *   ini ;
    int             rInt;
    // const char*  rSrc;

    fprintf(stderr, "[%04d]:filename->%s\n",__LINE__, filename);
    ini = iniparser_load(filename);
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return -1 ;
    }

    rInt = iniparser_getint(ini, "camera_chip_info:pseudo_color", -1);
    if(rInt >= 0){
        chip_ctrl->pseudo_color = rInt;
    }
     
    double tmp = iniparser_getdouble(ini, "camera_chip_info:electronic_zoom", 1.0);
    if(tmp >= 0){
        chip_ctrl->electronic_zoom = tmp;
    }

    rInt = iniparser_getint(ini, "camera_chip_info:shutter_calibration", -1);
    if(rInt >= 0){
        chip_ctrl->shutter_calibration = rInt;
    }

    rInt = iniparser_getint(ini, "camera_chip_info:outdoor_mode", -1);
    if(rInt >= 0){
        chip_ctrl->outdoor_mode = rInt;
    }

    iniparser_freedict(ini);
    return 0 ;
}

int get_rtspurl_from_ini(void *url)
{
    char*filename = CONFIG_INI_NAME;
    dictionary  *   ini ;
    int             rInt;
    const char*     rSrc;

    fprintf(stderr, "[%04d]:filename->%s\n",__LINE__, filename);
    ini = iniparser_load(filename);
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return -1 ;
    }

    rSrc = iniparser_getstring(ini, "rtsp_url:url", NULL);
    if(NULL == rSrc){
        fprintf(stderr, "[%04d]:rtsp_url:url is NULL\n",__LINE__);
        iniparser_freedict(ini);
        return -1;
    }
    strncpy(url, rSrc, strlen(rSrc));

    fprintf(stdout, "[%04d]:rtsp_url:url is %s\n",__LINE__, url);

    iniparser_freedict(ini);
    return 0 ;
}

int write_rtspurl_to_ini(void *st)
{
    char* filename = CONFIG_INI_NAME;

    void *dictionary;
    FILE *ini_file;
    const char*     rSrc;
    char ipaddr[16] = {0};

    dictionary = iniparser_load(filename);
    if (!dictionary) {
        fprintf(stderr, "cannot parse file: %s\n", filename);
        return -1;
    }

      /* set section */
    int ret = iniparser_set(dictionary, "rtsp_url", NULL);
    if (ret < 0) {
        fprintf(stderr, "cannot set section in: %s\n", filename);
        ret = -1;
        goto free_dict;
    }

    rSrc = iniparser_getstring(dictionary, "network:ipv4_addr", "192.168.110.178");
    if(rSrc){
        strncpy(ipaddr, rSrc, IP_ADDR_MAX_LENGTH - 1);
    }else{
        strncpy(ipaddr, "192.168.110.178", IP_ADDR_MAX_LENGTH - 1);//默认ip
    }

    /* set key/value pair */
    char tmpSRc[1024] = {0};
    snprintf(tmpSRc, sizeof(tmpSRc),"rtsp://%s:554/mainstream", ipaddr);
    ret = iniparser_set(dictionary, "rtsp_url:url", tmpSRc);
    if (ret < 0) {
        fprintf(stderr, "cannot set key/value in: %s\n", filename);
        goto free_dict;
    }

    ini_file = fopen(filename, "w+");
    if (!ini_file) {
        fprintf(stderr, "iniparser: cannot create example.ini\n");
        goto free_dict;
    }

    iniparser_dump_ini(dictionary, ini_file);
    fclose(ini_file);

free_dict:
    iniparser_freedict(dictionary);
    return ret;
}

int modify_yml(char *dstip)
{
  if(!dstip){
    fprintf(stderr, "ip is null!\n");
    return -1;
  }
  
  char command[BUFFER_SIZE];
    // sed -i 's/rtsp:\/\/192\.168\.110\.[0-9]\{1,3\}:554\/mainstream/rtsp:\/\/192\.168\.110\.100:554\/mainstream/g'
  snprintf(command, sizeof(command), "sed -i 's/rtsp:\\/\\/192\\.168\\.110\\.[0-9]\\{1,3\\}:554\\/mainstream/rtsp:\\/\\/%s:554\\/mainstream/g' %s", dstip, CONFIG_MEDIAMTX_YML);
  printf("command:%s\n",command);

  int result = system(command);

  if (result == -1) {
      perror("system call failed");
      return -1;
  }

  return 0;
}

double  get_memory_usage() {
    FILE *fp = fopen("/proc/meminfo", "r");
    if (fp == NULL) {
        perror("fopen");
        return -1;
    }

    unsigned long total_memory = 0, free_memory = 0, buffers = 0, cached = 0;

    char line[MAX_LINE];
    while (fgets(line, MAX_LINE, fp)) {
        if (strncmp(line, "MemTotal:", 9) == 0) {
            sscanf(line, "MemTotal: %lu kB", &total_memory);
        } else if (strncmp(line, "MemFree:", 8) == 0) {
            sscanf(line, "MemFree: %lu kB", &free_memory);
        } else if (strncmp(line, "Buffers:", 8) == 0) {
            sscanf(line, "Buffers: %lu kB", &buffers);
        } else if (strncmp(line, "Cached:", 7) == 0) {
            sscanf(line, "Cached: %lu kB", &cached);
        }
    }

    fclose(fp);

    // 计算剩余内存百分比 (不包含缓存和缓冲区)
    printf("total_memory=%lu,free_memory=%lu,buffers=%lu,cached=%lu\n",total_memory,free_memory, buffers, cached);
    unsigned long used_memory = total_memory - free_memory - buffers - cached;
    double memory_usage = ((used_memory) * 100.0 )/ total_memory ;
    return memory_usage;
}

double get_cpu_usage() {
    FILE *fp;
    unsigned long user1, nice1, system1, idle1, iowait1, irq1, softirq1, steal1;
    unsigned long user2, nice2, system2, idle2, iowait2, irq2, softirq2, steal2;
    unsigned long total_time1, idle_time1, total_time2, idle_time2;
    double cpu_usage = 0.0;

    // 第一次读取
    fp = fopen("/proc/stat", "r");
    if (!fp) {
        perror("Failed to open /proc/stat");
        return -1;
    }
    fscanf(fp, "cpu %lu %lu %lu %lu %lu %lu %lu %lu", 
           &user1, &nice1, &system1, &idle1, &iowait1, &irq1, &softirq1, &steal1);
    fclose(fp);

    // 等待 500ms 后读取第二次数据
    usleep(300000); // 100ms
    fp = fopen("/proc/stat", "r");
    if (!fp) {
        perror("Failed to open /proc/stat");
        return -1;
    }
    fscanf(fp, "cpu %lu %lu %lu %lu %lu %lu %lu %lu", 
           &user2, &nice2, &system2, &idle2, &iowait2, &irq2, &softirq2, &steal2);
    fclose(fp);

    // 计算两次采样的总时间和空闲时间
    total_time1 = user1 + nice1 + system1 + idle1 + iowait1 + irq1 + softirq1 + steal1;
    idle_time1 = idle1 + iowait1;

    total_time2 = user2 + nice2 + system2 + idle2 + iowait2 + irq2 + softirq2 + steal2;
    idle_time2 = idle2 + iowait2;

    // 确保 total_time2 > total_time1
    if (total_time2 > total_time1) {
        cpu_usage = (double)(100 * (1.0 - (double)(idle_time2 - idle_time1) / (total_time2 - total_time1)));
    }

    return cpu_usage;
}

int get_physical_addr(const char *interface, char *mac){
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("socket");
        return -1;
    }

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);

    if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
        perror("ioctl");
        close(sock);
        return -1;
    }

    close(sock);
    snprintf(mac,MAC_LENGTH,"%02x:%02x:%02x:%02x:%02x:%02x", 
    ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2],
    ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
    return 0;
}

int set_network_config(const char *interface, const char *ip, const char *netmask, const char *gateway) {
    char command[512];

    // 设置 IP 地址
    snprintf(command, sizeof(command), "ifconfig %s %s netmask %s", interface, ip, netmask);
    printf("Executing: %s\n", command);
    int result = system(command);
    if (result != 0) {
        fprintf(stderr, "Failed to set IP address for interface %s\n", interface);
        return -1; // 设置 IP 失败
    }

    // 设置网关
    snprintf(command, sizeof(command), "route add default gw %s", gateway);
    printf("Executing: %s\n", command);
    result = system(command);
    if (result != 0) {
        fprintf(stderr, "Failed to set gateway\n");
        return -1; // 设置网关失败
    }

    printf("Network configuration updated successfully.\n");
    return 0; // 成功
}

int save_network_config(NetworkConfigNetworkTcpIp *net_info)
{
    if (!net_info) {
        return -1;
    }

    const char *section = "network";
    const char *keys[] = {
        "ipv4_addr",
        "ipv4_gateway",
        "ipv4_mask",
        "dns"
    };
    const void *values[] = {
        net_info->ipv4_addr,
        net_info->ipv4_gateway,
        net_info->ipv4_mask,
        net_info->dns
    };
    int types[] = {0, 0, 0, 0}; /* 全部为字符串类型 */
    int count = 4;

    return write_config_to_ini(section, keys, values, types, count);
}

/* 使用通用接口读取网络配置 */
int load_network_config(NetworkConfigNetworkTcpIp *net_info)
{
    if (!net_info) {
        return -1;
    }

    const char *section = "network";
    const char *keys[] = {
        "ipv4_addr",
        "ipv4_gateway",
        "ipv4_mask",
        "dns"
    };
    
    void *values[] = {
        net_info->ipv4_addr,
        net_info->ipv4_gateway,
        net_info->ipv4_mask,
        net_info->dns
    };
    
    void *default_values[] = {
        "192.168.110.178",
        "192.168.110.1",
        "255.255.255.0",
        "8.8.8.8"
    };

    int types[] = {0, 0, 0, 0}; /* 全部为字符串类型 */
    int count = 4;

    /* 默认值为NULL */
    return read_config_from_ini(section, keys, values, types, default_values, count);
}

int save_camera_chip_config(NetworkCameraChipInfo *chip_info)
{
    if (!chip_info) {
        return -1;
    }

    printf("chip_info->electronic_zoom:%0.2f\n",chip_info->electronic_zoom);
    const char *section = "camera_chip_info";
    const char *keys[] = {
        "pseudo_color",
        "electronic_zoom",
        "shutter_calibration",
        "outdoor_mode",
        "vertical_flip",
        "horizontal_mirror"
    };
    
    /* 注意：对于非字符串类型，必须传递指针 */
    const void *values[] = {
        &chip_info->pseudo_color,
        &chip_info->electronic_zoom,
        &chip_info->shutter_calibration,
        &chip_info->outdoor_mode,
        &chip_info->vertical_image_flip,
        &chip_info->horizontal_image_flip
    };
    
    int types[] = {1, 2, 1, 1, 1, 1}; /* 整数、浮点数、整数、整数 */
    int count = sizeof(types)/sizeof(types[0]);

    return write_config_to_ini(section, keys, values, types, count);
}

int load_camera_chip_config(NetworkCameraChipInfo *chip_info)
{
    if (!chip_info) {
        return -1;
    }

    const char *section = "camera_chip_info";
    const char *keys[] = {
        "pseudo_color",
        "electronic_zoom",
        "shutter_calibration",
        "outdoor_mode",
        "vertical_flip",
        "horizontal_mirror"
    };
    
    void *values[] = {
        &chip_info->pseudo_color,
        &chip_info->electronic_zoom,
        &chip_info->shutter_calibration,
        &chip_info->outdoor_mode,
        &chip_info->vertical_image_flip,
        &chip_info->horizontal_image_flip
    };
    
    void *default_values[] = { &(int){0}, &(double){1.0}, &(int){1}, &(int){0},  &(int){0}, &(int){0}  };

    int types[] = {1, 2, 1, 1, 1, 1}; /* 整数、浮点数、整数、整数 */
    int count =  sizeof(types)/sizeof(types[0]);

    /* 可以提供默认值，但这里简化为NULL */
    return read_config_from_ini(section, keys, values, types, default_values, count);
}

/**
 * @brief 保存OSD配置信息到INI文件
 * 
 * @param osd_info OSD配置信息结构体
 * @return int 成功返回0，失败返回负值
 */
int save_osd_info_to_ini(const NetworkConfigOsdInfo *osd_info)
{
    if ( !osd_info) {
        return -1;
    }

    const char *section = "osd_config_info";
    // 先清理该节内容，避免重复累积
    // clear_section_in_ini(section);


    const char *keys[50];  // 足够大的数组来存储所有键
    const void *values[50];
    int types[50];
    int count = 0;
    int i;
    char key_buffer[50][64]; // 为动态生成的键名存储空间

    // 摄像头名称配置
    keys[count] = "show_camera_name";
    values[count] = &osd_info->show_camera_name;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "camera_name";
    values[count] = osd_info->camera_name;
    types[count] = VALUE_TYPE_STRING;
    count++;

    keys[count] = "camera_name_pos_x";
    values[count] = &osd_info->camera_name_pos.x;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "camera_name_pos_y";
    values[count] = &osd_info->camera_name_pos.y;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    // 日期和星期配置
    keys[count] = "show_date";
    values[count] = &osd_info->show_date;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "show_week";
    values[count] = &osd_info->show_week;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "date_pos_x";
    values[count] = &osd_info->date_pos.x;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "date_pos_y";
    values[count] = &osd_info->date_pos.y;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    // 字符叠加配置
    for (i = 0; i < NETWORK_CONFIG_OSD_INFO_STRING_OVERLAY_MAX; i++) {
        snprintf(key_buffer[count], 64, "string_overlay_%d_show", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].show;
        types[count] = VALUE_TYPE_INTEGER;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_value", i);
        keys[count] = key_buffer[count];
        values[count] = osd_info->string_overlay[i].value;
        types[count] = VALUE_TYPE_STRING;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_pos_x", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].pos.x;
        types[count] = VALUE_TYPE_INTEGER;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_pos_y", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].pos.y;
        types[count] = VALUE_TYPE_INTEGER;
        count++;
    }

    // OSD属性配置
    keys[count] = "osd_attribute_color";
    values[count] = osd_info->osd_attribute.color;
    types[count] = VALUE_TYPE_STRING;
    count++;

    keys[count] = "osd_attribute_size";
    values[count] = &osd_info->osd_attribute.size;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "osd_attribute_flicker";
    values[count] = &osd_info->osd_attribute.flicker;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    keys[count] = "osd_attribute_transparency";
    values[count] = &osd_info->osd_attribute.transparency;
    types[count] = VALUE_TYPE_INTEGER;
    count++;

    printf("================================save count: %d\n", count);
    return write_config_to_ini(section, keys, values, types, count);
}

/**
 * @brief 从INI文件读取OSD配置信息
 * 
 * @param osd_info OSD配置信息结构体
 * @return int 成功返回0，失败返回负值
 */
int load_osd_info_from_ini(NetworkConfigOsdInfo *osd_info)
{
    if (!osd_info) {
        return -1;
    }

    const char *section = "osd_config_info";
    // 设置默认值
    NetworkConfigOsdInfo default_osd_info = {
        .show_camera_name = 0,
        .camera_name = "Vot_Camera",
        .camera_name_pos = {0, 10},
        .show_date = 1,
        .show_week = 1,
        .date_pos = {0, 0},
        .string_overlay = {
            {0, "", {0, 0}},
            {0, "", {0, 0}},
            {0, "", {0, 0}},
            {0, "", {0, 0}}
        },
        .osd_attribute = {
            .color = "#FFFFFF",
            .size = 3,
            .flicker = 0,
            .transparency = 0
        }
    };

    // 复制默认值到输出参数
    memcpy(osd_info, &default_osd_info, sizeof(NetworkConfigOsdInfo));

    const char *keys[50];
    void *values[50];
    int types[50];
    const void *defaults[50];
    int count = 0;
    int i;
    char key_buffer[50][64];

    // 摄像头名称配置
    keys[count] = "show_camera_name";
    values[count] = &osd_info->show_camera_name;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.show_camera_name;
    count++;

    keys[count] = "camera_name";
    values[count] = osd_info->camera_name;
    types[count] = VALUE_TYPE_STRING;
    defaults[count] = default_osd_info.camera_name;
    count++;

    keys[count] = "camera_name_pos_x";
    values[count] = &osd_info->camera_name_pos.x;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.camera_name_pos.x;
    count++;

    keys[count] = "camera_name_pos_y";
    values[count] = &osd_info->camera_name_pos.y;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.camera_name_pos.y;
    count++;

    // 日期和星期配置
    keys[count] = "show_date";
    values[count] = &osd_info->show_date;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.show_date;
    count++;

    keys[count] = "show_week";
    values[count] = &osd_info->show_week;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.show_week;
    count++;

    keys[count] = "date_pos_x";
    values[count] = &osd_info->date_pos.x;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.date_pos.x;
    count++;

    keys[count] = "date_pos_y";
    values[count] = &osd_info->date_pos.y;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.date_pos.y;
    count++;

    // 字符叠加配置
    for (i = 0; i < NETWORK_CONFIG_OSD_INFO_STRING_OVERLAY_MAX; i++) {
        snprintf(key_buffer[count], 64, "string_overlay_%d_show", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].show;
        types[count] = VALUE_TYPE_INTEGER;
        defaults[count] = &default_osd_info.string_overlay[i].show;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_value", i);
        keys[count] = key_buffer[count];
        values[count] = osd_info->string_overlay[i].value;
        types[count] = VALUE_TYPE_STRING;
        defaults[count] = default_osd_info.string_overlay[i].value;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_pos_x", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].pos.x;
        types[count] = VALUE_TYPE_INTEGER;
        defaults[count] = &default_osd_info.string_overlay[i].pos.x;
        count++;

        snprintf(key_buffer[count], 64, "string_overlay_%d_pos_y", i);
        keys[count] = key_buffer[count];
        values[count] = &osd_info->string_overlay[i].pos.y;
        types[count] = VALUE_TYPE_INTEGER;
        defaults[count] = &default_osd_info.string_overlay[i].pos.y;
        count++;
    }

    // OSD属性配置
    keys[count] = "osd_attribute_color";
    values[count] = osd_info->osd_attribute.color;
    types[count] = VALUE_TYPE_STRING;
    defaults[count] = default_osd_info.osd_attribute.color;
    count++;

    keys[count] = "osd_attribute_size";
    values[count] = &osd_info->osd_attribute.size;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.osd_attribute.size;
    count++;

    keys[count] = "osd_attribute_flicker";
    values[count] = &osd_info->osd_attribute.flicker;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.osd_attribute.flicker;
    count++;

    keys[count] = "osd_attribute_transparency";
    values[count] = &osd_info->osd_attribute.transparency;
    types[count] = VALUE_TYPE_INTEGER;
    defaults[count] = &default_osd_info.osd_attribute.transparency;
    count++;

    // printf("================================read count: %d\n", count);
    return read_config_from_ini(section, keys, values, types, defaults, count);
} 

/**
 * @brief 通用INI配置存储函数
 * 
 * @param section 配置节名称
 * @param keys 键名数组
 * @param values 值数组
 * @param types 值类型数组 (0:字符串, 1:整数, 2:浮点数)
 * @param count 键值对数量
 * @return int 成功返回0，失败返回负值
 */
int write_config_to_ini(const char *section, const char **keys, const void **values, const int *types, int count)
{
    char *filename = CONFIG_INI_NAME;
    dictionary *dict = NULL;
    FILE *ini_file = NULL;
    int fd = -1;
    int ret = -1;
    int i;
    char full_key[128] = {0};
    char value_str[64] = {0};

    if (!section || !keys || !values || !types || count <= 0) {
        fprintf(stderr, "Invalid arguments\n");
        return -1;
    }

    /* 打开文件并加锁 */
    fd = open(filename, O_RDWR | O_CREAT, 0644);
    if (fd < 0) {
        fprintf(stderr, "Cannot open file: %s\n", filename);
        return -1;
    }

    /* 加独占写锁 */
    if (flock(fd, LOCK_EX) < 0) {
        fprintf(stderr, "Cannot lock file: %s\n", filename);
        close(fd);
        return -1;
    }

    /* 加载字典 */
    dict = iniparser_load(filename);
    if (!dict) {
        /* 如果文件不存在或为空，创建新字典 */
        dict = dictionary_new(0);
        if (!dict) {
            fprintf(stderr, "Cannot create dictionary\n");
            goto unlock_file;
        }
    }

    /* 设置节名 */
    ret = iniparser_set(dict, section, NULL);
    if (ret < 0) {
        fprintf(stderr, "Cannot set section: %s\n", section);
        goto free_dict;
    }

    /* 设置所有键值对 */
    for (i = 0; i < count; i++) {
        snprintf(full_key, sizeof(full_key), "%s:%s", section, keys[i]);
       
        switch (types[i]) {
            case VALUE_TYPE_STRING:
                // printf("full_key[%s],keys[%d]=%s, value[%d]=%s\n",full_key, i, keys[i],i, values[i]);
                ret = iniparser_set(dict, full_key, (const char *)values[i]);
                break;
            case VALUE_TYPE_INTEGER:
                // printf("full_key[%s],keys[%d]=%s, value[%d]=%d\n",full_key, i, keys[i],i, *(int*)values[i]);
                snprintf(value_str, sizeof(value_str), "%d", *((int *)values[i]));
                ret = iniparser_set(dict, full_key, value_str);
                break;
            case VALUE_TYPE_FLOAT:
                // printf("full_key[%s],keys[%d]=%s, value[%d]=%f\n",full_key, i, keys[i],i, *(float*)values[i]);
                snprintf(value_str, sizeof(value_str), "%f", *((float *)values[i]));
                ret = iniparser_set(dict, full_key, value_str);
                break;
            default:
                fprintf(stderr, "Unsupported value type: %d\n", types[i]);
                continue;
        }
        
        if (ret < 0) {
            fprintf(stderr, "Cannot set key/value: %s\n", full_key);
            goto free_dict;
        }
    }

    /* 写入文件 */
    ini_file = fopen(filename, "w+");
    if (!ini_file) {
        fprintf(stderr, "iniparser: cannot create example.ini\n");
        goto free_dict;
    }

    iniparser_dump_ini(dict, ini_file);
    fclose(ini_file);
    ret = 0;  /* 操作成功 */

free_dict:
    iniparser_freedict(dict);
unlock_file:
    /* 解锁并关闭文件 */
    flock(fd, LOCK_UN);
    close(fd);
    return ret;
}

/**
 * @brief 通用INI配置读取函数
 * 
 * @param section 配置节名称
 * @param keys 键名数组
 * @param values 值存储数组
 * @param types 值类型数组 (0:字符串, 1:整数, 2:浮点数)
 * @param default_values 默认值数组(可为NULL)
 * @param count 键值对数量
 * @return int 成功返回0，失败返回负值
 */
int read_config_from_ini(const char *section, const char **keys, void **values, const int *types, const void **default_values, int count)
{
    char *filename = CONFIG_INI_NAME;
    dictionary *dict = NULL;
    int fd = -1;
    int ret = -1;
    int i;
    char full_key[128] = {0};
    const char *str_val = NULL;
    int int_val;
    double dbl_val;

    if (!section || !keys || !values || !types || count <= 0) {
        fprintf(stderr, "Invalid arguments\n");
        return -1;
    }

    /* 打开文件并加锁 */
    fd = open(filename, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Cannot open file: %s\n", filename);
        return -1;
    }

    /* 加共享读锁 */
    if (flock(fd, LOCK_SH) < 0) {
        fprintf(stderr, "Cannot lock file: %s\n", filename);
        close(fd);
        return -1;
    }

    /* 加载字典 */
    dict = iniparser_load(filename);
    if (!dict) {
        fprintf(stderr, "Cannot parse file: %s\n", filename);
        goto unlock_file;
    }

    /* 读取所有键值对 */
    for (i = 0; i < count; i++) {
        snprintf(full_key, sizeof(full_key), "%s:%s", section, keys[i]);
        
        switch (types[i]) {
            case VALUE_TYPE_STRING:
                str_val = iniparser_getstring(dict, full_key, 
                          default_values ? (const char *)default_values[i] : NULL);
                if (str_val) {
                    strcpy((char *)values[i], str_val);
                }
                break;
            case VALUE_TYPE_INTEGER:
                int_val = iniparser_getint(dict, full_key, 
                          default_values ? *((int *)default_values[i]) : -1);
                if (int_val != -1 || (default_values && *((int *)default_values[i]) == -1)) {
                    *((int *)values[i]) = int_val;
                }
                break;
            case VALUE_TYPE_FLOAT:
                dbl_val = iniparser_getdouble(dict, full_key, 
                          default_values ? *((float *)default_values[i]) : -1.0);
                if (dbl_val != -1.0 || (default_values && *((float *)default_values[i]) == -1.0)) {
                    *((float *)values[i]) = dbl_val;
                }
                break;
            default:
                fprintf(stderr, "Unsupported value type: %d\n", types[i]);
                continue;
        }
    }

    ret = 0;  /* 操作成功 */
    iniparser_freedict(dict);

unlock_file:
    /* 解锁并关闭文件 */
    flock(fd, LOCK_UN);
    close(fd);
    return ret;
}
